- 基础优化 (数据/索引): 优化的分块策略、元数据增强。
- 查询优化 (预处理): 查询重写(如 HyDE)、查询扩展。
- 核心优化 (检索): 混合检索、领域特定嵌入模型精调。
- 结果优化 (后处理): 重排序 (Re-ranking) 和上下文压缩。
强调 RAG 优化的目标是:提高召回率 (Recall)(确保相关信息被找到)和提高准确率 (Precision)(确保找到的信息确实相关且高质量) 供高质量上下文。
一、数据准备和索引优化:构建高质量检索“地基”
该阶段的核心是让数据更易被精准检索,通过优化数据的物理组织形式和索引结构,降低后续检索的难度。
1. 优化的分块策略:让每块数据“语义完整”
分块的本质是将非结构化文本转化为适合嵌入和检索的基本单元,技术实现围绕“语义连贯性”和“检索精准性”展开。
- 语义分块:基于NLP工具(如spaCy、NLTK)的句法分析能力,识别句子边界(句号、感叹号)、段落标记,确保分割点落在语义完整的单元末尾。更进阶的实现会结合语义角色标注(SRL),确保一个块内包含完整的“主谓宾”逻辑或核心观点。
- 重叠分块:在机械分块或语义分块的基础上,设置固定重叠长度(如每块500字符,重叠100字符)。实现时通过滑动窗口机制,前一个窗口的末尾部分与后一个窗口的开头部分重叠,避免跨块信息断裂。
- 动态分块:先通过文档解析工具(如Unstructured、PyPDF2)识别内容类型(标题、代码块、表格、列表),再针对不同类型设置分块规则。例如,代码块按函数/类完整分割,标题作为元数据关联到下属段落块,列表按条目分组分块。
- “小-大”检索:构建双层索引结构。第一层索引“小块”(如100-200字符),用于快速定位与查询高度相关的精准片段;第二层存储“大块”(如1000-2000字符)或原始文档结构。检索时,先通过小块找到候选位置,再回溯提取其所属的大块作为上下文输入LLM。
2. 元数据增强:给数据加“标签”,提升过滤能力
通过结构化标签为每个块附加额外信息,实现检索时的精准筛选,技术实现分为“元数据生成”和“元数据检索”两步。
- 元数据生成:在分块过程中,同步提取或生成元数据。基础元数据(来源、日期、作者)可从文档属性直接获取;高级元数据(章节标题、主题关键词)可通过LLM或关键词提取算法(如TF-IDF、TextRank)从块内容或文档结构中生成,并与块向量绑定存储。
- 元数据过滤:检索时,将用户查询中的筛选条件(如“2024年发布的技术文档”)转化为元数据查询语句,在向量检索前或检索后,对结果进行过滤。例如,在向量数据库(如Pinecone、Weaviate)中,支持将元数据作为过滤条件与向量相似度查询结合,仅返回符合元数据条件的块。
3. 索引结构优化:让检索“有的放矢”
通过多索引和高级嵌入策略,提升索引对不同查询场景的适配性。
- 多索引与查询路由:为不同类型的数据(如技术文档、产品手册、用户问答)分别构建独立索引。同时训练一个路由模型(可基于轻量LLM或分类模型),根据用户查询的语义(如“如何使用XX功能”偏向产品手册),判断查询所属类别,将其路由到对应的索引进行检索,避免跨索引的无效匹配。
- 摘要/标题嵌入:对每个文档块或整篇文档,使用LLM生成简短摘要(如50-100字符)或提取核心标题,将摘要/标题的嵌入向量与原始块向量一同存储。检索时,可先通过摘要/标题向量进行初步筛选(减少计算量),再对筛选后的结果进行原始块向量的精细匹配,平衡效率与准确性。
二、查询处理优化:让检索“读懂”用户意图
该阶段通过对原始查询的改造,弥补用户表达的模糊性,生成更贴合检索需求的查询语句,提升检索的针对性。
1. 查询重写:将模糊查询转化为精准检索语句
核心是通过语义理解,修正查询中的歧义、指代不清等问题,生成更适合检索的表达。
- 基础语义重写:利用LLM(如GPT-3.5-turbo、Llama)对原始查询进行“检索友好化”改写。例如,处理指代消解(“它的工作原理是什么?”→“XX产品的工作原理是什么?”)、补充省略信息(“如何优化?”→“如何优化RAG系统的检索准确率?”),输出更完整、关键词更明确的查询。
- HyDE(假设性文档嵌入):技术实现分为三步。第一步,输入用户查询到LLM,指令其生成一个“假设性的理想答案”(无需真实存在,仅需符合查询语义);第二步,将生成的假设答案进行嵌入,得到假设文档向量;第三步,用该向量替代原始查询向量进行检索。其核心逻辑是:假设答案包含了查询的核心语义和潜在相关信息,用其向量检索能更精准匹配目标文档。
2. 查询扩展:扩大检索范围,提升召回率
通过补充相关概念,让检索覆盖更多潜在相关的文档,避免因关键词缺失导致的漏检。
- 实现逻辑:先对原始查询进行关键词提取(如使用TF-IDF或LLM提取核心术语),再通过知识库(如WordNet、维基百科)或LLM生成关键词的同义词、上下位词、相关概念(如“AI”→“人工智能”“机器学习”“深度学习”),将这些扩展词与原始查询组合,形成新的扩展查询,再执行检索。
- 优势:解决用户查询中关键词与文档中表述不一致的问题(如用户说“电脑”,文档说“计算机”),提高召回率。
3. 多查询生成:拆解复杂问题,实现精准匹配
针对多意图、多步骤的复杂查询,通过拆解为子查询,分别检索后汇总,确保每个子意图都能得到匹配。
- 实现流程:第一步,输入复杂查询到LLM,指令其拆解为多个独立的、单一意图的子问题(如“如何用Python实现RAG的混合检索?”→“1. Python中如何实现BM25检索?2. Python中如何实现向量检索?3. Python中如何融合BM25与向量检索结果?”);第二步,为每个子问题生成对应的检索查询;第三步,分别执行每个子查询的检索,获取子结果;第四步,将所有子结果合并,作为最终上下文输入LLM。
三、检索算法优化:提升匹配的精准度与全面性
该阶段通过选择和组合不同的检索算法,结合数据特点和查询需求,平衡关键词匹配与语义匹配的优势。
1. 混合检索:融合稀疏与密集检索的优势
核心是同时利用稀疏检索的“关键词精准性”和密集检索的“语义关联性”,实现更全面的匹配。
- 技术实现:
- 双路检索:对用户查询同时执行两种检索。一路是稀疏检索(如BM25),基于关键词的词频、逆文档频率计算相关性;另一路是密集检索(如基于BERT的向量检索),将查询和文档转化为向量后计算余弦相似度。
- 结果融合:通过Reciprocal Rank Fusion (RRF) 算法融合两路结果。RRF的公式为:
score(d) = sum(1/(k + rank(d, q_i))),其中rank(d, q_i)是文档d在第i个查询结果中的排名,k为常数(通常取60)。该算法无需对两路结果的分数进行归一化,能有效平衡不同检索方式的结果权重,最终输出融合后的排序结果。
2. 精调嵌入模型:让嵌入向量更贴合领域语义
通用嵌入模型(如Sentence-BERT)在特定领域(如医疗、法律)的语义捕捉能力有限,通过领域数据精调,优化嵌入空间。
- 实现步骤:
- 数据准备:收集领域内的文本数据(如医疗文献、法律条文),构建精调数据集,通常采用“句子对”形式(如相关句子对、不相关句子对)。
- 精调目标:使用对比学习(Contrastive Learning)或三元组损失(Triplet Loss)作为训练目标。对比学习要求模型将相关句子对的向量距离拉近,不相关句子对的向量距离拉远;三元组损失则要求“锚点句子”与“正例句子”的距离小于“锚点句子”与“负例句子”的距离。
- 训练执行:基于预训练的通用嵌入模型(如all-MiniLM-L6-v2),使用领域数据集进行微调,更新模型参数,使模型学习到领域内特有的语义关联。
- 效果验证:通过领域内的检索任务(如召回率、准确率)验证精调后模型的性能提升。
3. 图检索:利用结构化关系提升检索精准度
当知识库包含实体和关系信息(如知识图谱)时,通过图查询获取实体关联信息,补充语义检索的不足。
- 技术实现:
- 知识图谱构建:将非结构化文本中的实体(如“RAG”“向量检索”“BM25”)和关系(如“包含”“基于”“融合”)抽取出来,构建知识图谱,存储于图数据库(如Neo4j、NebulaGraph)中。
- 图查询生成:将用户查询中的实体和关系意图转化为图查询语句(如Cypher)。例如,查询“RAG包含哪些检索方法?”→转化为Cypher语句:
MATCH (n:Concept {name:"RAG"})-[r:CONTAINS]->(m:RetrievalMethod) RETURN m.name。 - 结果融合:将图检索得到的结构化实体关系信息,与向量检索得到的非结构化文本信息融合,作为上下文输入LLM,使回答既包含语义内容,又具备结构化的关系逻辑。
四、检索结果后处理:优化最终输入LLM的上下文质量
该阶段对初次检索的结果进行二次优化,剔除冗余、筛选核心信息,提升LLM利用上下文的效率和准确性。
1. 重排序(Re-ranking):提升Top-K结果的精准度
初次检索(如向量检索、混合检索)的结果排序可能存在偏差,通过更强大的模型二次评估相关性,优化排序。
- 技术实现:
- 初次检索:通过向量检索或混合检索获取Top-K(如Top-100)候选结果,此时的排序基于初步的相似度计算(如余弦相似度、RRF分数)。
- Cross-Encoder重打分:使用Cross-Encoder模型对“查询-文档块”对进行二次打分。与用于向量生成的Bi-Encoder不同,Cross-Encoder会同时输入查询和文档块的完整文本,通过Transformer层进行深度交互,直接输出两者的相关性分数,能更精准地捕捉语义匹配度。
- 重新排序:根据Cross-Encoder输出的相关性分数,对初次检索的Top-K结果重新排序,选取Top-N(如Top-10)结果作为最终上下文,大幅提升结果的准确率。
2. 上下文压缩:聚焦核心信息,降低Token消耗
检索到的文档块中可能包含大量与查询无关的信息,通过压缩提取核心内容,优化LLM输入。
- 实现方式:
- 基于LLM的压缩:将“查询+文档块”输入LLM,指令其仅提取与查询高度相关的句子或段落(如“请从以下文档块中,提取与‘RAG分块策略’相关的核心内容,保持原意,精简表达”),输出压缩后的文本。
- 基于关键词的过滤:提取查询的核心关键词,通过关键词匹配度(如TF-IDF权重)筛选文档块中包含关键词或相关表述的句子,剔除无关句子,实现压缩。
- 价值:减少输入LLM的Token数量,降低成本;同时避免LLM因上下文过长而出现“迷失在中间”的问题,提升回答的相关性。
3. 冗余消除:确保信息多样性,提升上下文效率
检索结果中可能存在重复或高度相似的文档块,通过去重保证信息的多样性。
- 技术实现:
- 相似度计算:对检索到的文档块两两计算相似度,可使用文本相似度算法(如余弦相似度、Jaccard相似度)或基于嵌入向量的相似度。
- 冗余判定:设定相似度阈值(如0.8),当两个文档块的相似度超过阈值时,判定为冗余。
- 去重策略:保留相似度较高的文档块中排序更靠前(相关性更高)的一个,删除其余冗余块;或对冗余块进行合并,提取共同核心信息,避免重复输入。